package io_demo;

import org.junit.*;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.*;
import java.util.Arrays;

/**
 * 本类只要看前两个方法即可！！！  一个是拷贝文件，一个是编码解码字符集知识
 */
@SpringBootTest
public class FileStreamTestDemo {
    /**
     * 字节流的例子：拷贝文件方法
     *  使用FileInputStream 读文件，使用FileOutStream 写文件
     */
    @Test
    public void copyFile(){
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try{
            long start = System.currentTimeMillis();
            fis = new FileInputStream("D:\\work\\file\\d.txt");
            fos = new FileOutputStream("D:\\work\\file\\copy1.txt");
            int len;
            //1024个字节  1024=1KB 1024\*1024\*5 = 5MB  使用1024的整数倍，文件装的满
            //使用bytes数组做容器，一次读取5MB数据，直到读到文件末尾-1结束
            byte[] bytes = new byte[1024 * 1024 * 5];
            //字节输入流的read方法，读文件
            // 如果不传入参数，返回的是读取到的单个字节。
            // 如果传入参数字节数组，则返回字节数组会存入读取到的值，而返回值就是读取的长度
            while((len = fis.read(bytes)) != -1){
                System.out.println(len);
                //字节输出流的write方法，写文件，使用数组进行写入，从0开始，一次读len长
                fos.write(bytes,0,len);
            }
            //使用完毕关闭资源
            fis.close();
            fos.close();
            long end = System.currentTimeMillis();
            System.out.println(end - start);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //释放资源
            //先关文件输出流，再关文件输入流
            //后用的先释放
            if (fos != null){
                try{
                    fos.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
            if (fis != null){
                try{
                    fis.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 扩展知识
     * 字符集
     * GBK 存中文2字节，2的16位，可以存65536   6万个汉字
     * 为了让计算机底层，区分中文和英文 汉字编码用1开头，英文编码用0开头
     * 1开头是汉字，连续读2个字节
     * GBK字符集完全兼容ASCII字符集
     *
     *  Unicode字符集（把全世界的语言的每个字符定义为唯一的编码）的UTF-8（Unicode字符集的一种编码方式） 一个英文一个字节 二进制第一位是0 转成十进制是正数
     *  一个中文占三个字节，二进制第一位是1，第一个字节转成十进制是负数
     *
     *  乱码：1、读取数据时未读取到完整的汉字 2、编码和解码方式不一致
     *
     *  避免乱码：1、不用字节流读取文本文件，2、编码解码时使用同一个码表，同一个编码方式
     */
    /**
     *  string类中的编码方法   public byte[] getBytes()    使用默认方式进行编码
     *                      public byte[] getBytes(String charsetName)    使用指定方式进行编码
     *
     *  String类中的解码方式   String(byte[] bytes)   使用默认方式进行解码
     *                      String(byte[] bytes,String charsetName)   使用指定方式进行解码
     */
    @Test
    public void codeTestDemo() throws UnsupportedEncodingException {
        String str = "ai你哟";
        byte[] bytes1 = str.getBytes();
        System.out.println(Arrays.toString(bytes1));//[97, 105, -28, -67, -96, -27, -109, -97]

        byte[] bytes2 = str.getBytes("GBK");
        System.out.println(Arrays.toString(bytes2));//[97, 105, -60, -29, -45, -76]

        //同一个字节数组，bytes1，使用默认解码 ，使用指定的GBK进行解码，得到的结果不一样
        String str2 = new String(bytes1);
        System.out.println("str2:"+str2);//str2:ai你哟

        String str3 = new String(bytes1,"GBK");
        System.out.println("str3:"+str3);//str3:ai浣犲摕

    }





    //文件输出流
    @Test
    public void outputdemo(){
        try{
            //FileOutputStream传入文件名称
            FileOutputStream fos1 = new FileOutputStream("D:\\work\\file\\a.txt");
            fos1.write(97);
            fos1.close();

            //FileOutputStream传入File类
            File file = new File("D:\\work\\file\\b.txt");
            FileOutputStream fos2 = new FileOutputStream(file);
            fos2.write(98);
            fos2.close();

            //write传入字节数组
            FileOutputStream fos3 = new FileOutputStream("D:\\work\\file\\c.txt");
            byte[] bytes = {97,98,99};
            fos3.write(bytes);
            fos3.close();

            //write传入字节数组,截取部分
            FileOutputStream fos4 = new FileOutputStream("D:\\work\\file\\d.txt");
            byte[] bytes2 = {97,98,99};
            fos4.write(bytes2,0,2);
            fos4.close();

            //write传入字节数组,截取部分,续写
            FileOutputStream fos5 = new FileOutputStream("D:\\work\\file\\d.txt",true);
            byte[] bytes3 = {97,98,99};
            fos5.write(bytes3,0,2);
            fos5.close();

            //传入字符串
            String str = "字符串";
            FileOutputStream fos6 = new FileOutputStream("D:\\work\\file\\d.txt",true);
            byte[] bytes4 = str.getBytes();
            fos6.write(bytes4);
            fos6.close();

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    //文件输入流
    @Test
    public void inputdemo(){
        try{
            FileInputStream fis = new FileInputStream("D:\\work\\file\\d.txt");
            int b1 = fis.read();
            System.out.println((char)b1);

            //需要定义第三方参数接收read读取的字节，因为read读取指针会移动
            // 末尾结束符是-1
            int b;
            while((b = fis.read()) != -1 ){
                System.out.print((char)b);
            }
            //
        }catch (Exception e){
            e.printStackTrace();
        }

    }



    //继续搞 IO流的 P10 TestDemo
}
